package xyz.yuzegod.megawalls.game.team;

import com.google.common.base.Predicate;
import net.citizensnpcs.api.CitizensAPI;
import net.minecraft.server.v1_8_R3.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_8_R3.event.CraftEventFactory;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.plugin.Plugin;
import xyz.yuzegod.megawalls.MegaWalls;
import xyz.yuzegod.megawalls.game.Game;
import xyz.yuzegod.megawalls.game.GamePlayer;
import xyz.yuzegod.megawalls.game.GameTeam;
import xyz.yuzegod.megawalls.game.stage.BattleStage;
import xyz.yuzegod.megawalls.stats.CurrencyPackage;
import xyz.yuzegod.megawalls.stats.EffectStatsContainer;
import xyz.yuzegod.megawalls.util.PlayerUtils;

import java.util.HashMap;
import java.util.Map;

public class TeamWither extends EntityWither
{
    private final Game game;
    private static final Predicate<Entity> bq;
    private int[] bn;
    private int[] bo;
    private int bp;
    private GameTeam gameTeam;
    private boolean warning;
    private boolean deepRed;
    private Map<GamePlayer, Float> damagerList;
    
    public TeamWither(final World world) {
        super(world);
        this.bn = new int[2];
        this.bo = new int[2];
        this.gameTeam = null;
        this.warning = false;
        this.deepRed = true;
        this.damagerList = new HashMap<GamePlayer, Float>();
        this.game = MegaWalls.getInstance().getGame();
    }
    
    public void setTeam(final GameTeam gameTeam) {
        if (gameTeam == null) {
            this.gameTeam = gameTeam;
        }
        this.setCustomName(gameTeam.getTeamColor().getChatColor() + gameTeam.getTeamColor().getText() + " §l凋零");
        this.setCustomNameVisible(true);
    }
    
    public GameTeam getGameTeam() {
        if (this.gameTeam != null) {
            return this.gameTeam;
        }
        final String name = ChatColor.stripColor(this.getCustomName()).substring(0, 1);
        final GameTeam gameTeam = this.game.getTeamByName(name);
        if (this.gameTeam == null) {
            this.gameTeam = gameTeam;
        }
        return gameTeam;
    }
    
    public EntityLiving getGoalTarget() {
        for (final Player player : PlayerUtils.getNearbyPlayers(this.getBukkitEntity().getLocation(), 10.0)) {
            if (CitizensAPI.getNPCRegistry().isNPC((org.bukkit.entity.Entity)player)) {
                continue;
            }
            final GamePlayer gamePlayer = GamePlayer.get(player.getUniqueId());
            if (gamePlayer.isSpectator()) {
                continue;
            }
            if (this.getGameTeam().isInTeam(gamePlayer)) {
                continue;
            }
            return (EntityLiving)((CraftPlayer)player).getHandle();
        }
        return null;
    }
    
    protected void E() {
        if (this.cl() > 0) {
            final int i = this.cl() - 1;
            if (i <= 0) {
                final ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Entity)this.getBukkitEntity(), 7.0f, false);
                this.world.getServer().getPluginManager().callEvent((Event)event);
                if (!event.isCancelled()) {
                    this.world.createExplosion((Entity)this, this.locX, this.locY + this.getHeadHeight(), this.locZ, event.getRadius(), event.getFire(), this.world.getGameRules().getBoolean("mobGriefing"));
                }
                final int viewDistance = this.world.getServer().getViewDistance() * 16;
                for (final EntityPlayer player : MinecraftServer.getServer().getPlayerList().players) {
                    final double deltaX = this.locX - player.locX;
                    final double deltaZ = this.locZ - player.locZ;
                    final double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
                    if (this.world.spigotConfig.witherSpawnSoundRadius <= 0 || distanceSquared <= this.world.spigotConfig.witherSpawnSoundRadius * this.world.spigotConfig.witherSpawnSoundRadius) {
                        if (distanceSquared > viewDistance * viewDistance) {
                            final double deltaLength = Math.sqrt(distanceSquared);
                            final double relativeX = player.locX + deltaX / deltaLength * viewDistance;
                            final double relativeZ = player.locZ + deltaZ / deltaLength * viewDistance;
                            player.playerConnection.sendPacket((Packet)new PacketPlayOutWorldEvent(1013, new BlockPosition((int)relativeX, (int)this.locY, (int)relativeZ), 0, true));
                        }
                        else {
                            player.playerConnection.sendPacket((Packet)new PacketPlayOutWorldEvent(1013, new BlockPosition((int)this.locX, (int)this.locY, (int)this.locZ), 0, true));
                        }
                    }
                }
            }
            this.r(i);
            if (this.ticksLived % 10 == 0) {
                this.heal(10.0f, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN);
            }
        }
        else {
            if (this.getGoalTarget() != null) {
                this.b(0, this.getGoalTarget().getId());
            }
            else {
                this.b(0, 0);
            }
            if (this.bp > 0) {
                --this.bp;
                if (this.bp == 0 && this.world.getGameRules().getBoolean("mobGriefing")) {
                    final int i = MathHelper.floor(this.locY);
                    final int j = MathHelper.floor(this.locX);
                    final int j2 = MathHelper.floor(this.locZ);
                    boolean flag = false;
                    for (int k1 = -1; k1 <= 1; ++k1) {
                        for (int l1 = -1; l1 <= 1; ++l1) {
                            for (int i2 = 0; i2 <= 3; ++i2) {
                                final int j3 = j + k1;
                                final int k2 = i + i2;
                                final int l2 = j2 + l1;
                                final BlockPosition blockposition = new BlockPosition(j3, k2, l2);
                                final Block block = this.world.getType(blockposition).getBlock();
                                if (block.getMaterial() != Material.AIR && a(block) && !CraftEventFactory.callEntityChangeBlockEvent((Entity)this, j3, k2, l2, Blocks.AIR, 0).isCancelled()) {
                                    flag = (this.world.setAir(blockposition, true) || flag);
                                }
                            }
                        }
                    }
                    if (flag) {
                        this.world.a((EntityHuman)null, 1012, new BlockPosition((Entity)this), 0);
                    }
                }
            }
            if (this.ticksLived % 20 == 0) {
                this.heal(1.0f, EntityRegainHealthEvent.RegainReason.REGEN);
            }
        }
    }
    
    private void a(final int i, final EntityLiving entityliving) {
        this.a(i, entityliving.locX, entityliving.locY + entityliving.getHeadHeight() * 0.5, entityliving.locZ, i == 0 && this.random.nextFloat() < 0.001f);
    }
    
    private void a(final int i, final double d0, final double d1, final double d2, final boolean flag) {
        this.world.a((EntityHuman)null, 1014, new BlockPosition((Entity)this), 0);
        final double d3 = this.t(i);
        final double d4 = this.u(i);
        final double d5 = this.v(i);
        final double d6 = d0 - d3;
        final double d7 = d1 - d4;
        final double d8 = d2 - d5;
        final EntityWitherSkull entitywitherskull = new EntityWitherSkull(this.world, (EntityLiving)this, d6, d7, d8);
        if (flag) {
            entitywitherskull.setCharged(true);
        }
        entitywitherskull.locY = d4;
        entitywitherskull.locX = d3;
        entitywitherskull.locZ = d5;
        this.world.addEntity((Entity)entitywitherskull);
    }
    
    private double t(final int i) {
        if (i <= 0) {
            return this.locX;
        }
        final float f = (this.aI + 180 * (i - 1)) / 180.0f * 3.141593f;
        final float f2 = MathHelper.cos(f);
        return this.locX + f2 * 1.3;
    }
    
    private double u(final int i) {
        return (i <= 0) ? (this.locY + 3.0) : (this.locY + 2.2);
    }
    
    private double v(final int i) {
        if (i <= 0) {
            return this.locZ;
        }
        final float f = (this.aI + 180 * (i - 1)) / 180.0f * 3.141593f;
        final float f2 = MathHelper.sin(f);
        return this.locZ + f2 * 1.3;
    }
    
    public void move(final double d0, final double d1, final double d2) {
    }
    
    protected void dropDeathLoot(final boolean flag, final int i) {
    }
    
    public void die() {
        GamePlayer.getOnlinePlayers().forEach(viewer -> {
            EffectStatsContainer effectStats;
            effectStats = viewer.getPlayerStats().getEffectStats();
            viewer.sendMessage(effectStats.getColor(this.getGameTeam().getTeamColor()).getChatColor() + this.getGameTeam().getTeamColor().getText() + "队凋零§e死亡！");
            viewer.sendMessage(effectStats.getColor(this.getGameTeam().getTeamColor()).getChatColor() + this.getGameTeam().getTeamColor().getText() + "队§e玩家无法再复活");
            return;
        });
        this.getGameTeam().setWitherDead(true);
        this.game.broadcastSound(Sound.ENDERDRAGON_GROWL, 1.0f, 1.0f, (GamePlayer[])this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
        this.game.broadcastMessage("§b凋零已死,你无法再复活！", this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
        this.game.broadcastTitle("§c我方凋零死亡！", "§e你无法再复活了！", 5, 20, 5, (GamePlayer[])this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
        boolean allDead = true;
        for (final GameTeam gameTeam : this.game.getTeams()) {
            if (!gameTeam.isWitherDead()) {
                allDead = false;
                break;
            }
        }
        if (!this.game.isDeathMatch() && allDead) {
            ((BattleStage)this.game.getStageManager().getStage(3)).setCacheLeft(this.game.getStageManager().getSeconds());
            this.game.getStageManager().setSeconds(0);
            this.game.getStageManager().setCurrentStage(99);
            this.game.broadcastTitle("§c所有的凋零都死了！", "§f死斗模式将在§b10§f秒后开启！", 10, 40, 10);
            this.game.broadcastMessage("§c§l所有的凋零已经死亡！还有§b§l10§c§l秒开启死斗模式！");
        }
        for (GamePlayer gamePlayer : this.damagerList.keySet()) {
            ((BattleStage)this.game.getStageManager().getStage(3)).setCacheLeft(this.game.getStageManager().getSeconds());
            gamePlayer.getPlayerStats().giveCoins(new CurrencyPackage(64, "(凋零伤害奖励)"));
        }
        super.die();
    }
    
    public boolean damageEntity(final DamageSource damagesource, final float f) {
        if (!this.game.isWallsFall()) {
            return true;
        }
        if (damagesource.equals(DamageSource.GENERIC)) {
            return super.damageEntity(damagesource, f);
        }
        if (damagesource != null && damagesource.getEntity() != null && damagesource.getEntity().getBukkitEntity() != null && damagesource.getEntity().getBukkitEntity() instanceof CraftPlayer) {
            final Player player = (Player)damagesource.getEntity().getBukkitEntity();
            if (CitizensAPI.getNPCRegistry().isNPC((org.bukkit.entity.Entity)player)) {
                return true;
            }
            final GamePlayer gamePlayer = GamePlayer.get(player.getUniqueId());
            if (!gamePlayer.isSpectator() && !this.getGameTeam().isInTeam(gamePlayer)) {
                if (!this.warning) {
                    this.warning = true;
                    this.deepRed = !this.deepRed;
                    this.game.broadcastMessage((this.deepRed ? "§4" : "§c") + "§l我方凋零正在被攻击！", (GamePlayer[])this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                    this.game.broadcastTitle("", (this.deepRed ? "§4" : "§c") + "§l我方凋零正在被攻击！", 0, 40, 0, (GamePlayer[])this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                    this.game.broadcastAction((this.deepRed ? "§4" : "§c") + "§l我方凋零正在被攻击！", (GamePlayer[])this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                    this.game.broadcastSound(Sound.NOTE_PLING, 1.0f, 2.0f, (GamePlayer[])this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                    Bukkit.getScheduler().runTaskLater((Plugin)MegaWalls.getInstance(), (Runnable)new Runnable() {
                        @Override
                        public void run() {
                            TeamWither.this.game.broadcastSound(Sound.NOTE_PLING, 1.0f, 3.0f, (GamePlayer[])TeamWither.this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                            TeamWither.this.game.broadcastAction((TeamWither.this.deepRed ? "§4" : "§c") + "§l我方凋零正在被攻击！", (GamePlayer[])TeamWither.this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                        }
                    }, 11L);
                    Bukkit.getScheduler().runTaskLater((Plugin)MegaWalls.getInstance(), (Runnable)new Runnable() {
                        @Override
                        public void run() {
                            TeamWither.this.game.broadcastSound(Sound.NOTE_PLING, 1.0f, 3.0f, (GamePlayer[])TeamWither.this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                            TeamWither.this.game.broadcastAction((TeamWither.this.deepRed ? "§4" : "§c") + "§l我方凋零正在被攻击！", (GamePlayer[])TeamWither.this.getGameTeam().getAlivePlayers().toArray(new GamePlayer[0]));
                        }
                    }, 22L);
                    Bukkit.getScheduler().runTaskLater((Plugin)MegaWalls.getInstance(), (Runnable)new Runnable() {
                        @Override
                        public void run() {
                            TeamWither.this.warning = false;
                        }
                    }, 60L);
                }
                this.damagerList.put(gamePlayer, this.damagerList.getOrDefault(gamePlayer, 0.0f) + f / 5.0f);
                return super.damageEntity(damagesource, f / 5.0f);
            }
        }
        return true;
    }
    
    static {
        bq = (Predicate)new Predicate<Entity>() {
            public boolean a(final Entity entity) {
                return entity instanceof EntityLiving && ((EntityLiving)entity).getMonsterType() != EnumMonsterType.UNDEAD;
            }
            
            public boolean apply(final Entity entity) {
                return this.a(entity);
            }
        };
    }
}
